"""
Flask HTTP客户端示例 - 展示HTTP请求、API集成和外部服务调用
包含同步/异步请求、重试机制、响应处理等功能
"""

from flask import Flask, request, jsonify, g
import os
import sys
import time
import asyncio
from datetime import datetime
from typing import Dict, Any, Optional, List
import json

# 添加项目根目录到Python路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from python_backend_toolkit.http_client import (
    HTTPClient, AsyncHTTPClient, RequestConfig,
    RetryConfig, TimeoutConfig
)
from python_backend_toolkit.logging import get_logger
from python_backend_toolkit.utils import generate_uuid
from python_backend_toolkit.api.responses import SuccessResponse, ErrorResponse


def create_http_client_app() -> Flask:
    """创建HTTP客户端示例Flask应用"""
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'http-client-demo-secret'
    
    # 初始化HTTP客户端
    sync_client = HTTPClient(
        base_url="https://jsonplaceholder.typicode.com",
        timeout=TimeoutConfig(connect=5, read=10),
        retry=RetryConfig(max_attempts=3, backoff_factor=1.0)
    )
    
    async_client = AsyncHTTPClient(
        base_url="https://httpbin.org",
        timeout=TimeoutConfig(connect=5, read=10),
        retry=RetryConfig(max_attempts=3, backoff_factor=1.0)
    )
    
    logger = get_logger("HTTPClientApp")
    
    @app.before_request
    def before_request():
        """请求前处理"""
        g.request_id = generate_uuid()
        g.start_time = time.time()
    
    @app.after_request
    def after_request(response):
        """请求后处理"""
        duration = time.time() - g.start_time
        logger.info(
            "Request completed",
            request_id=g.request_id,
            method=request.method,
            path=request.path,
            status_code=response.status_code,
            duration=duration
        )
        return response
    
    # ========================================================================
    # 基础HTTP请求示例
    # ========================================================================
    
    @app.route('/http/get-example', methods=['GET'])
    def get_example():
        """GET请求示例"""
        try:
            # 获取JSONPlaceholder的用户列表
            response = sync_client.get("/users")
            
            if response.is_success:
                users = response.json()
                
                # 处理数据
                processed_users = []
                for user in users[:5]:  # 只取前5个用户
                    processed_users.append({
                        "id": user["id"],
                        "name": user["name"],
                        "username": user["username"],
                        "email": user["email"],
                        "website": user.get("website", ""),
                        "company": user.get("company", {}).get("name", "")
                    })
                
                result = SuccessResponse.create(
                    data={
                        "users": processed_users,
                        "total": len(processed_users),
                        "source": "JSONPlaceholder API"
                    },
                    message="Users retrieved successfully"
                )
                return jsonify(result.dict())
            else:
                return jsonify(ErrorResponse.create(
                    message=f"Failed to fetch users: {response.status_code}"
                ).dict()), 500
                
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Request failed: {str(e)}"
            ).dict()), 500
    
    @app.route('/http/post-example', methods=['POST'])
    def post_example():
        """POST请求示例"""
        data = request.get_json()
        
        try:
            # 向JSONPlaceholder发送POST请求
            post_data = {
                "title": data.get("title", "Test Post"),
                "body": data.get("body", "This is a test post"),
                "userId": data.get("userId", 1)
            }
            
            response = sync_client.post("/posts", json=post_data)
            
            if response.is_success:
                created_post = response.json()
                
                result = SuccessResponse.create(
                    data={
                        "post": created_post,
                        "original_data": post_data
                    },
                    message="Post created successfully"
                )
                return jsonify(result.dict()), 201
            else:
                return jsonify(ErrorResponse.create(
                    message=f"Failed to create post: {response.status_code}"
                ).dict()), 500
                
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Request failed: {str(e)}"
            ).dict()), 500
    
    @app.route('/http/put-example/<int:post_id>', methods=['PUT'])
    def put_example(post_id: int):
        """PUT请求示例"""
        data = request.get_json()
        
        try:
            # 向JSONPlaceholder发送PUT请求
            put_data = {
                "id": post_id,
                "title": data.get("title", "Updated Post"),
                "body": data.get("body", "This is an updated post"),
                "userId": data.get("userId", 1)
            }
            
            response = sync_client.put(f"/posts/{post_id}", json=put_data)
            
            if response.is_success:
                updated_post = response.json()
                
                result = SuccessResponse.create(
                    data={
                        "post": updated_post,
                        "original_data": put_data
                    },
                    message="Post updated successfully"
                )
                return jsonify(result.dict())
            else:
                return jsonify(ErrorResponse.create(
                    message=f"Failed to update post: {response.status_code}"
                ).dict()), 500
                
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Request failed: {str(e)}"
            ).dict()), 500
    
    @app.route('/http/delete-example/<int:post_id>', methods=['DELETE'])
    def delete_example(post_id: int):
        """DELETE请求示例"""
        try:
            response = sync_client.delete(f"/posts/{post_id}")
            
            if response.is_success:
                result = SuccessResponse.create(
                    data={"deleted_post_id": post_id},
                    message="Post deleted successfully"
                )
                return jsonify(result.dict())
            else:
                return jsonify(ErrorResponse.create(
                    message=f"Failed to delete post: {response.status_code}"
                ).dict()), 500
                
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Request failed: {str(e)}"
            ).dict()), 500
    
    # ========================================================================
    # 异步HTTP请求示例
    # ========================================================================
    
    @app.route('/http/async-get', methods=['GET'])
    def async_get_example():
        """异步GET请求示例"""
        async def make_async_request():
            try:
                # 使用httpbin.org进行测试
                response = await async_client.get("/json")
                
                if response.is_success:
                    data = response.json()
                    return SuccessResponse.create(
                        data={
                            "response": data,
                            "headers": dict(response.headers),
                            "status_code": response.status_code
                        },
                        message="Async GET request successful"
                    )
                else:
                    return ErrorResponse.create(
                        message=f"Async request failed: {response.status_code}"
                    )
                    
            except Exception as e:
                return ErrorResponse.create(
                    message=f"Async request failed: {str(e)}"
                )
        
        try:
            result = asyncio.run(make_async_request())
            status_code = 200 if isinstance(result, SuccessResponse) else 500
            return jsonify(result.dict()), status_code
            
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Async operation failed: {str(e)}"
            ).dict()), 500
    
    @app.route('/http/async-post', methods=['POST'])
    def async_post_example():
        """异步POST请求示例"""
        data = request.get_json()
        
        async def make_async_request():
            try:
                # 向httpbin.org发送POST请求
                response = await async_client.post("/post", json=data)
                
                if response.is_success:
                    response_data = response.json()
                    return SuccessResponse.create(
                        data={
                            "echo": response_data,
                            "original_data": data
                        },
                        message="Async POST request successful"
                    )
                else:
                    return ErrorResponse.create(
                        message=f"Async request failed: {response.status_code}"
                    )
                    
            except Exception as e:
                return ErrorResponse.create(
                    message=f"Async request failed: {str(e)}"
                )
        
        try:
            result = asyncio.run(make_async_request())
            status_code = 200 if isinstance(result, SuccessResponse) else 500
            return jsonify(result.dict()), status_code
            
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Async operation failed: {str(e)}"
            ).dict()), 500
    
    # ========================================================================
    # 并发请求示例
    # ========================================================================
    
    @app.route('/http/concurrent-requests', methods=['GET'])
    def concurrent_requests():
        """并发请求示例"""
        async def make_concurrent_requests():
            try:
                # 创建多个并发请求
                tasks = []
                
                # 请求不同的端点
                endpoints = [
                    "/json",
                    "/uuid",
                    "/user-agent",
                    "/headers",
                    "/ip"
                ]
                
                for endpoint in endpoints:
                    task = async_client.get(endpoint)
                    tasks.append(task)
                
                # 等待所有请求完成
                responses = await asyncio.gather(*tasks, return_exceptions=True)
                
                results = []
                for i, response in enumerate(responses):
                    if isinstance(response, Exception):
                        results.append({
                            "endpoint": endpoints[i],
                            "success": False,
                            "error": str(response)
                        })
                    else:
                        results.append({
                            "endpoint": endpoints[i],
                            "success": response.is_success,
                            "status_code": response.status_code,
                            "data": response.json() if response.is_success else None
                        })
                
                return SuccessResponse.create(
                    data={
                        "results": results,
                        "total_requests": len(endpoints),
                        "successful_requests": sum(1 for r in results if r["success"])
                    },
                    message="Concurrent requests completed"
                )
                
            except Exception as e:
                return ErrorResponse.create(
                    message=f"Concurrent requests failed: {str(e)}"
                )
        
        try:
            start_time = time.time()
            result = asyncio.run(make_concurrent_requests())
            duration = time.time() - start_time
            
            if isinstance(result, SuccessResponse):
                result.data["execution_time"] = round(duration, 3)
            
            status_code = 200 if isinstance(result, SuccessResponse) else 500
            return jsonify(result.dict()), status_code
            
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Concurrent operation failed: {str(e)}"
            ).dict()), 500
    
    # ========================================================================
    # 重试机制示例
    # ========================================================================
    
    @app.route('/http/retry-example', methods=['GET'])
    def retry_example():
        """重试机制示例"""
        try:
            # 创建一个会失败的客户端来演示重试
            retry_client = HTTPClient(
                base_url="https://httpbin.org",
                timeout=TimeoutConfig(connect=1, read=2),  # 很短的超时
                retry=RetryConfig(max_attempts=3, backoff_factor=2.0)
            )
            
            # 请求一个会延迟的端点
            delay = request.args.get('delay', 5)  # 默认5秒延迟
            response = retry_client.get(f"/delay/{delay}")
            
            if response.is_success:
                data = response.json()
                result = SuccessResponse.create(
                    data={
                        "response": data,
                        "delay_requested": delay,
                        "retry_info": "Request succeeded (possibly after retries)"
                    },
                    message="Request with retry successful"
                )
                return jsonify(result.dict())
            else:
                return jsonify(ErrorResponse.create(
                    message=f"Request failed after retries: {response.status_code}"
                ).dict()), 500
                
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Request failed with retries: {str(e)}"
            ).dict()), 500
    
    # ========================================================================
    # 文件上传示例
    # ========================================================================
    
    @app.route('/http/upload-example', methods=['POST'])
    def upload_example():
        """文件上传示例"""
        try:
            # 检查是否有文件
            if 'file' not in request.files:
                return jsonify(ErrorResponse.create(
                    message="No file provided"
                ).dict()), 400
            
            file = request.files['file']
            if file.filename == '':
                return jsonify(ErrorResponse.create(
                    message="No file selected"
                ).dict()), 400
            
            # 准备文件数据
            files = {'file': (file.filename, file.stream, file.content_type)}
            
            # 向httpbin.org上传文件
            response = sync_client.post("/post", files=files)
            
            if response.is_success:
                upload_result = response.json()
                
                result = SuccessResponse.create(
                    data={
                        "filename": file.filename,
                        "content_type": file.content_type,
                        "upload_response": upload_result.get("files", {}),
                        "form_data": upload_result.get("form", {})
                    },
                    message="File uploaded successfully"
                )
                return jsonify(result.dict())
            else:
                return jsonify(ErrorResponse.create(
                    message=f"File upload failed: {response.status_code}"
                ).dict()), 500
                
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Upload failed: {str(e)}"
            ).dict()), 500
    
    # ========================================================================
    # API集成示例
    # ========================================================================
    
    @app.route('/http/weather', methods=['GET'])
    def weather_example():
        """天气API集成示例（模拟）"""
        city = request.args.get('city', 'Beijing')
        
        try:
            # 这里使用httpbin.org模拟天气API响应
            # 在实际应用中，你会调用真实的天气API
            mock_weather_data = {
                "city": city,
                "temperature": 22,
                "humidity": 65,
                "description": "Partly cloudy",
                "wind_speed": 15,
                "timestamp": datetime.utcnow().isoformat()
            }
            
            # 模拟API调用
            response = sync_client.post("/post", json=mock_weather_data)
            
            if response.is_success:
                result = SuccessResponse.create(
                    data={
                        "weather": mock_weather_data,
                        "api_response": "Simulated weather API call",
                        "note": "This is a mock response. In production, use a real weather API."
                    },
                    message=f"Weather data for {city} retrieved successfully"
                )
                return jsonify(result.dict())
            else:
                return jsonify(ErrorResponse.create(
                    message="Weather API call failed"
                ).dict()), 500
                
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Weather API integration failed: {str(e)}"
            ).dict()), 500
    
    # ========================================================================
    # 响应处理示例
    # ========================================================================
    
    @app.route('/http/response-handling', methods=['GET'])
    def response_handling_example():
        """响应处理示例"""
        status_code = request.args.get('status', 200)
        
        try:
            # 请求httpbin.org的状态码端点
            response = sync_client.get(f"/status/{status_code}")
            
            # 处理不同的响应状态
            result_data = {
                "requested_status": status_code,
                "actual_status": response.status_code,
                "is_success": response.is_success,
                "headers": dict(response.headers),
                "response_time": getattr(response, 'elapsed', 'N/A')
            }
            
            # 根据状态码提供不同的处理
            if response.status_code == 200:
                result_data["message"] = "Request successful"
            elif response.status_code == 404:
                result_data["message"] = "Resource not found"
            elif response.status_code >= 500:
                result_data["message"] = "Server error occurred"
            else:
                result_data["message"] = f"Received status code {response.status_code}"
            
            # 尝试解析响应内容
            try:
                if response.content:
                    result_data["content"] = response.text[:200]  # 只显示前200个字符
            except:
                result_data["content"] = "Unable to parse response content"
            
            result = SuccessResponse.create(
                data=result_data,
                message="Response handling demonstration completed"
            )
            return jsonify(result.dict())
            
        except Exception as e:
            return jsonify(ErrorResponse.create(
                message=f"Response handling failed: {str(e)}"
            ).dict()), 500
    
    # ========================================================================
    # 应用信息
    # ========================================================================
    
    @app.route('/health', methods=['GET'])
    def health_check():
        """健康检查"""
        return jsonify({
            "status": "healthy",
            "timestamp": datetime.utcnow().isoformat()
        })
    
    @app.route('/info', methods=['GET'])
    def app_info():
        """应用信息"""
        return jsonify({
            "name": "Flask HTTP Client Example",
            "version": "1.0.0",
            "description": "Flask HTTP客户端功能示例应用",
            "endpoints": {
                "basic_requests": [
                    "GET    /http/get-example",
                    "POST   /http/post-example",
                    "PUT    /http/put-example/<id>",
                    "DELETE /http/delete-example/<id>"
                ],
                "async_requests": [
                    "GET  /http/async-get",
                    "POST /http/async-post",
                    "GET  /http/concurrent-requests"
                ],
                "advanced_features": [
                    "GET  /http/retry-example?delay=<seconds>",
                    "POST /http/upload-example",
                    "GET  /http/weather?city=<city>",
                    "GET  /http/response-handling?status=<code>"
                ]
            },
            "external_apis": {
                "jsonplaceholder": "https://jsonplaceholder.typicode.com",
                "httpbin": "https://httpbin.org"
            }
        })
    
    return app


if __name__ == '__main__':
    app = create_http_client_app()
    
    print("=" * 60)
    print("Flask HTTP Client Example")
    print("=" * 60)
    print("HTTP客户端功能演示:")
    print("  基础请求:")
    print("    GET    /http/get-example - GET请求示例")
    print("    POST   /http/post-example - POST请求示例")
    print("    PUT    /http/put-example/<id> - PUT请求示例")
    print("    DELETE /http/delete-example/<id> - DELETE请求示例")
    print()
    print("  异步请求:")
    print("    GET  /http/async-get - 异步GET请求")
    print("    POST /http/async-post - 异步POST请求")
    print("    GET  /http/concurrent-requests - 并发请求")
    print()
    print("  高级功能:")
    print("    GET  /http/retry-example?delay=<seconds> - 重试机制")
    print("    POST /http/upload-example - 文件上传")
    print("    GET  /http/weather?city=<city> - API集成示例")
    print("    GET  /http/response-handling?status=<code> - 响应处理")
    print()
    print("  外部API:")
    print("    JSONPlaceholder: https://jsonplaceholder.typicode.com")
    print("    HTTPBin: https://httpbin.org")
    print("=" * 60)
    
    app.run(
        host='0.0.0.0',
        port=5003,
        debug=True
    )